<!-- 列设置 -->
<template>
  <EleTool
    ref="toolRef"
    :title="locale.columns"
    :placement="placement"
    :clickHideTooltip="true"
  >
    <EleTooltip
      trigger="click"
      placement="bottom-end"
      popperClass="ele-tool-column-popover"
      transition="el-zoom-in-top"
      :gpuAcceleration="false"
      effect="light"
      :isPopover="true"
      :popperOptions="{
        strategy: 'fixed',
        modifiers: [{ name: 'offset', options: { offset: [20, 10] } }],
      }"
    >
      <ElIcon>
        <SettingOutlined />
      </ElIcon>
      <template #body>
        <div
          :class="[
            'ele-popover-body',
            'ele-tool-column',
            { 'is-sortable': sortable },
          ]"
        >
          <div class="ele-tool-column-header">
            <div class="ele-tool-column-label">
              <ElCheckbox
                :label="locale.columnTitle"
                :modelValue="isCheckAll"
                :indeterminate="isIndeterminate"
                @update:modelValue="handleCheckAllChange"
              />
            </div>
            <div class="ele-tool-column-link" @click="handleReset">
              {{ locale.columnReset }}
            </div>
          </div>
          <ToolColumnList
            v-if="colItems.length"
            :data="colItems"
            :sortable="sortable"
            :allowFixed="allowFixed"
            @sortChange="handleSortChange"
            @checkedChange="handleCheckedChange"
            @fixedLeft="handleFixedLeft"
            @fixedRight="handleFixedRight"
            @fixedLeftTooltip="handleFixedLeftTooltip"
            @fixedRightTooltip="handleFixedRightTooltip"
          />
        </div>
      </template>
    </EleTooltip>
  </EleTool>
</template>

<script setup>
import { ref, watch } from "vue";
import { ElCheckbox, ElIcon } from "element-plus";
import { SettingOutlined } from "../../icons/index";
import { eachTree } from "../../utils/common";
import EleTooltip from "../../ele-tooltip/index.vue";
import EleTool from "../../ele-tool/index.vue";
import {
  getCheckedColumns,
  getColsCacheKey,
  getColItems,
  getCacheCols,
  columnsSettingFilter,
  getCacheColsWidth,
} from "../util";
import ToolColumnList from "./tool-column-list.vue";

defineOptions({ name: "ToolColumn" });

const props = defineProps({
  /** 提示位置 */
  placement: String,
  /** 表格国际化 */
  locale: {
    type: Object,
    required: true,
  },
  /** 列数据 */
  columns: Array,
  /** 是否开启列拖拽排序 */
  sortable: Boolean,
  /** 是否开启开关固定列 */
  allowFixed: Boolean,
  /** 列配置缓存本地的名称 */
  cacheKey: String,
});

const emit = defineEmits({
  "update:columns": (_columns, _tableColumns, _isReset) => true,
});

/** 工具按钮 */
const toolRef = ref(null);

/** 列配置 */
const colItems = ref([]);

/** 是否全选 */
const isCheckAll = ref(false);

/** 是否半选 */
const isIndeterminate = ref(false);

/** 初始化数据 */
const initColItems = () => {
  const { cols, checkAll, indeterminate } = getColItems(
    props.columns,
    props.locale,
    columnsSettingFilter,
    getCacheCols(getColsCacheKey(props.cacheKey)),
  );
  colItems.value = cols;
  isCheckAll.value = checkAll;
  isIndeterminate.value = indeterminate;
};

/** 更新表格列配置 */
const updateColumns = (isReset) => {
  const colsWidth = getCacheColsWidth(props.cacheKey);
  const columns = getCheckedColumns(
    props.columns,
    colItems.value,
    props.sortable,
    (item) => item.hideInSetting,
    void 0,
    false,
    colsWidth,
  );
  const tableColumns = getCheckedColumns(
    props.columns,
    colItems.value,
    props.sortable,
    (item) => item.hideInSetting,
    void 0,
    true,
    colsWidth,
  );
  emit("update:columns", columns, tableColumns, !!isReset);
};

/** 缓存配置 */
const cacheSettingCols = () => {
  if (props.cacheKey) {
    localStorage.setItem(
      getColsCacheKey(props.cacheKey),
      JSON.stringify(colItems.value),
    );
  }
};

/** 清除缓存配置 */
const cleanSettingCols = () => {
  if (props.cacheKey) {
    localStorage.removeItem(getColsCacheKey(props.cacheKey));
  }
};

/** 选中改变 */
const handleCheckedChange = (item, checked) => {
  let checkAll = true;
  let indeterminate = false;
  eachTree(colItems.value, (d) => {
    if (d.uid === item.uid) {
      d.checked = checked;
    }
    if (!d.checked && checkAll) {
      checkAll = false;
    }
    if (d.checked && !indeterminate) {
      indeterminate = true;
    }
    if (d.uid === item.uid && !checkAll && indeterminate) {
      return false;
    }
  });
  isCheckAll.value = colItems.value.length > 0 && checkAll;
  isIndeterminate.value = !checkAll && indeterminate;
  cacheSettingCols();
  updateColumns();
};

/** 全选或取消全选 */
const handleCheckAllChange = (checked) => {
  isCheckAll.value = checked;
  isIndeterminate.value = false;
  eachTree(colItems.value, (d) => {
    if (d.checked !== checked) {
      d.checked = checked;
    }
  });
  cacheSettingCols();
  updateColumns();
};

/** 拖动顺序改变 */
const handleSortChange = (items, parent) => {
  if (!parent) {
    colItems.value = items;
  } else {
    eachTree(colItems.value, (d) => {
      if (d.uid === parent.uid) {
        d.children = items;
        return false;
      }
    });
  }
  cacheSettingCols();
  updateColumns();
};

/** 固定左侧 */
const handleFixedLeft = (colItem) => {
  eachTree(colItems.value, (d) => {
    if (d.uid === colItem.uid) {
      d.fixed = d.fixed === true || d.fixed === "left" ? false : "left";
      return false;
    }
  });
  cacheSettingCols();
  updateColumns();
};

/** 固定右侧 */
const handleFixedRight = (colItem) => {
  eachTree(colItems.value, (d) => {
    if (d.uid === colItem.uid) {
      d.fixed = d.fixed === "right" ? false : "right";
      return false;
    }
  });
  cacheSettingCols();
  updateColumns();
};

/** 固定左侧提示 */
const handleFixedLeftTooltip = (el) => {
  toolRef.value &&
    toolRef.value.showTooltip(props.locale.columnFixedLeft ?? "", el);
};

/** 固定右侧提示 */
const handleFixedRightTooltip = (el) => {
  toolRef.value &&
    toolRef.value.showTooltip(props.locale.columnFixedRight ?? "", el);
};

/** 重置 */
const handleReset = () => {
  cleanSettingCols();
  initColItems();
  updateColumns(true);
};

watch(
  [() => props.columns, () => props.locale],
  () => {
    initColItems();
  },
  { immediate: true, deep: true },
);
</script>
